﻿#include "ConfigDialog.hpp"
#include <FL/fl_ask.H>
#include <iostream>
using namespace std;



const char* WINDOW_TITLE = "M3G Exporter for Metasequoia";

ConfigDialog:: ConfigDialog () : 
    Fl_Window(100,100,350,326,WINDOW_TITLE),
    tabs(NULL), grp_tab_basic(NULL), grp_tab_advance(NULL),
    grp_export(NULL), btn_export_scene(NULL), btn_export_model(NULL),
    btn_export_ambient(NULL), btn_export_directional(NULL), btn_export_camera(NULL),
    grp_file(NULL), btn_file_compress(NULL), btn_file_log(NULL),
    grp_scene(NULL), inp_scene_scale(NULL), inp_scene_near(NULL), inp_scene_far(NULL),
    grp_accept(NULL), btn_accept_ok(NULL), btn_accept_cancel(NULL),
    grp_advanced(NULL), btn_advanced_rendering_layer(NULL)
{
    begin ();

    // Tab Group
    tabs = new Fl_Tabs (0,0,350,330,"Tabs");
    tabs->begin ();

    grp_tab_basic = new Fl_Group (0,24,350,306,"  Basic  ");
    grp_tab_basic->begin ();

    // Export Group
    grp_export = new Fl_Group (10,24+10,160,144 ,"Export");
    grp_export->box   (FL_EMBOSSED_FRAME);
    grp_export->align (FL_ALIGN_TOP|FL_ALIGN_INSIDE);
    grp_export->begin ();
    btn_export_scene       = new Fl_Radio_Round_Button (10+4 , 24+10+18 ,154, 24, "Scene");
    btn_export_model       = new Fl_Radio_Round_Button (10+4 , 24+10+110,154, 24, "Model");
    btn_export_ambient     = new Fl_Check_Button       (10+24, 24+10+42 ,124, 24, "Ambient light");
    btn_export_directional = new Fl_Check_Button       (10+24, 24+10+64 ,124, 24, "Directional light");
    btn_export_camera      = new Fl_Check_Button       (10+24, 24+10+86 ,124, 24, "Camera");
    grp_export->end   ();

    // File Group
    grp_file = new Fl_Group (10,24+164,160,76 ,"File"  );
    grp_file->box   (FL_EMBOSSED_FRAME);
    grp_file->align (FL_ALIGN_TOP|FL_ALIGN_INSIDE);
    grp_file->begin ();
    btn_file_compress = new Fl_Check_Button (10+4, 24+164+22,154,24, "compression");
    btn_file_log      = new Fl_Check_Button (10+4, 24+164+44,154,24, "log");
    grp_file->end   ();

    // Scene Group
    grp_scene = new Fl_Group (180,24+10,160,230,"Scene" );
    grp_scene->box   (FL_EMBOSSED_FRAME);
    grp_scene->align (FL_ALIGN_TOP|FL_ALIGN_INSIDE);
    grp_scene->begin ();
    inp_scene_scale = new Fl_Float_Input (180+48, 24+10+24, 60, 24, "Scale:");
    inp_scene_near  = new Fl_Float_Input (180+48, 24+10+52, 60, 24, "Near:");
    inp_scene_far   = new Fl_Float_Input (180+48, 24+10+80, 60, 24, "Far:");
    grp_scene->end   ();

    grp_tab_basic->end ();

    // タブ２(Advanced)
    grp_tab_advance = new Fl_Group (10,24,350,330,"Advanced");
    grp_tab_advance->begin ();

    // Advanced Group
    grp_advanced = new Fl_Group (10,24+10, 330, 230, "Advaned");
    grp_advanced->box   (FL_EMBOSSED_FRAME);
    grp_advanced->align (FL_ALIGN_TOP|FL_ALIGN_INSIDE);
    grp_advanced->begin ();
    btn_advanced_rendering_layer = new Fl_Check_Button (10+4,24+10+18,330,24,"Set rendering layer by object index");
    grp_advanced->end ();

    grp_tab_advance->end ();

    tabs->end ();

    // Accept Group
    grp_accept = new Fl_Group (218,24+250,122,56, NULL);
    grp_accept->begin ();
    btn_accept_ok     = new Fl_Return_Button (218+0 , 24+250+0, 56, 36, "OK");
    btn_accept_cancel = new Fl_Button        (218+66, 24+250+0, 56, 36, "Cancel");
    grp_accept->end   ();

    // 初期値
    btn_export_scene      ->value (true);
    btn_export_ambient    ->value (true);
    btn_export_directional->value (true);
    btn_export_camera     ->value (true);
    btn_file_compress     ->value (true);
    btn_file_log          ->value (true);
    inp_scene_scale       ->value ("1.0");
    inp_scene_near        ->value ("10.0");
    inp_scene_far         ->value ("10000.0");
    btn_advanced_rendering_layer->value (false);

    // コールバック
    this             ->callback (onCallbackWindow      , NULL);
    btn_export_scene ->callback (onCallbackExportScene , this);
    btn_export_model ->callback (onCallbackExportModel , this);
    btn_accept_ok    ->callback (onCallbackAcceptOK    , this);
    btn_accept_cancel->callback (onCallbackAcceptCancel, this);

    // デフォルトのフォーカス
    btn_accept_ok->take_focus ();

    end ();

    show ();
}

ConfigDialog:: ~ConfigDialog ()
{
    // 注意：
    // ウィジットはすべて自動でdeleteされるので
    // 自分でdeleteしないように！！
}


bool ConfigDialog:: run ()
{
    return Fl::run();
}


bool ConfigDialog:: getExportSceneEnalbed () const
{
    return result.export_scene_enabled;
}

bool ConfigDialog:: getExportAmbientLightEnabled () const
{
    return result.export_ambient_enabled;
}

bool ConfigDialog:: getExportDirectionalLightEnalbed () const
{
    return result.export_directional_enabled;
}

bool ConfigDialog:: getExportCameraEnalbed () const
{
    return result.export_camera_enabled;
}

bool ConfigDialog:: getExportModelEnalbed () const
{
    return result.export_model_enabled;
}

bool ConfigDialog:: getFileCompressEnabled () const
{
    return result.file_compress_enabled;
}

bool ConfigDialog:: getFileLogEnabled () const
{
    return result.file_log_enabled;
}

float ConfigDialog:: getSceneScaleFactor () const
{
    return result.scene_scale;
}

float ConfigDialog:: getSceneClippingNear () const
{
    return result.scene_near;
}

float ConfigDialog:: getSceneClippingFar () const
{
    return result.scene_far;
}

bool ConfigDialog:: getAdvanedRenderingLayerEnabled () const
{
    return result.rendering_layer;
}

bool ConfigDialog:: getAccepted () const
{
    return result.accepted;
}

void ConfigDialog:: onCallbackWindow (Fl_Widget* w, void* v)
{
    ConfigDialog* thiz = static_cast<ConfigDialog*>(w);
    thiz->result.accepted = false;
    thiz->hide ();
}


void ConfigDialog:: onCallbackExportScene (Fl_Widget* w, void* v)
{
    Fl_Round_Button* button = dynamic_cast<Fl_Round_Button*>(w);
    ConfigDialog*    thiz   = static_cast<ConfigDialog*>(v);
    if (button->value()) {
        thiz->btn_export_ambient    ->activate ();
        thiz->btn_export_directional->activate ();
        thiz->btn_export_camera     ->activate ();
    }
}

void ConfigDialog:: onCallbackExportModel (Fl_Widget* w, void* v)
{
    Fl_Round_Button* button = dynamic_cast<Fl_Round_Button*>(w);
    ConfigDialog*    thiz   = static_cast<ConfigDialog*>(v);
    if (button->value()) {
        thiz->btn_export_ambient    ->deactivate ();
        thiz->btn_export_directional->deactivate ();
        thiz->btn_export_camera     ->deactivate ();
    }

}

void ConfigDialog:: onCallbackAcceptOK     (Fl_Widget* w, void* v)
{
    ConfigDialog* thiz = static_cast<ConfigDialog*>(v);
    thiz->result.export_scene_enabled       = (bool)thiz->btn_export_scene      ->value ();
    thiz->result.export_ambient_enabled     = (bool)thiz->btn_export_ambient    ->value ();
    thiz->result.export_directional_enabled = (bool)thiz->btn_export_directional->value ();
    thiz->result.export_camera_enabled      = (bool)thiz->btn_export_camera     ->value ();
    thiz->result.export_model_enabled       = (bool)thiz->btn_export_model      ->value ();
    thiz->result.file_compress_enabled      = (bool)thiz->btn_file_compress     ->value ();
    thiz->result.file_log_enabled           = (bool)thiz->btn_file_log          ->value ();
    thiz->result.scene_scale                = atof(thiz->inp_scene_scale->value ());
    thiz->result.scene_near                 = atof(thiz->inp_scene_near ->value ());
    thiz->result.scene_far                  = atof(thiz->inp_scene_far  ->value ());
    thiz->result.rendering_layer            = (bool)thiz->btn_advanced_rendering_layer->value ();

    bool error = false;
    string s ("Error!,\nValues should be:\n");
    if (!(thiz->result.scene_scale > 0)) {
        s    += "  Scale > 0\n";
        error = true;
    }
    if (!(thiz->result.scene_near > 0)) {
        s    += "  Near > 0\n";
        error = true;
    }
    if (!(thiz->result.scene_far > 0)) {
        s    += "  Far > 0\n";
        error = true;
    }
    if (!(thiz->result.scene_far > thiz->result.scene_near)) {
        s    += "  Far > Near\n";
        error = true;
    }
    if (error) {
        fl_message ("%s", s.c_str());
        return;
    }

    thiz->result.accepted  = true;
    thiz->hide ();
}

void ConfigDialog:: onCallbackAcceptCancel (Fl_Widget* w, void* v)
{
    ConfigDialog* thiz = static_cast<ConfigDialog*>(v);
    thiz->result.accepted = false;
    thiz->hide ();
}
